<template>
  <div class="container">
    <canvas class="fireworks"></canvas>
  </div>
</template>

<script>
import anime from "@/assets/js/anime.min.js"

export default {
  name: "fireworks",
  data() {
    return {
      canvasEl: null,
      pointerX: 0,
      pointerY: 0,
      ctx: null,
    }
  },
  mounted() {
    window.human = false

    this.canvasEl = document.querySelector(".fireworks")

    this.ctx = this.canvasEl.getContext("2d")

    var tap = "ontouchstart" in window || navigator.msMaxTouchPoints ? "touchstart" : "mousedown"

    let that = this
    var render = anime({
      duration: Infinity,
      update: function () {
        that.ctx.clearRect(0, 0, that.canvasEl.width, that.canvasEl.height)
      },
    })

    document.addEventListener(
      tap,
      function (e) {
        window.human = true
        render.play()
        that.updateCoords(e)
        that.animateParticules(that.pointerX, that.pointerY)
      },
      false
    )

    this.setCanvasSize()

    window.addEventListener("resize", that.setCanvasSize, false)
  },
  methods: {
    setCanvasSize() {
      this.canvasEl.width = window.innerWidth * 2
      this.canvasEl.height = window.innerHeight * 2
      this.canvasEl.style.width = window.innerWidth + "px"
      this.canvasEl.style.height = window.innerHeight + "px"
      this.canvasEl.getContext("2d").scale(2, 2)
    },
    updateCoords(e) {
      this.pointerX = e.clientX || e.touches[0].clientX
      this.pointerY = e.clientY || e.touches[0].clientY
    },
    setParticuleDirection(p) {
      var angle = (anime.random(0, 360) * Math.PI) / 180
      var value = anime.random(50, 180)
      var radius = [-1, 1][anime.random(0, 1)] * value
      return {
        x: p.x + radius * Math.cos(angle),
        y: p.y + radius * Math.sin(angle),
      }
    },
    createParticule(x, y) {
      var colors = ["#FF1461", "#18FF92", "#5A87FF", "#FBF38C"]

      var p = {}
      p.x = x
      p.y = y
      p.color = colors[anime.random(0, colors.length - 1)]
      p.radius = anime.random(16, 32)
      p.endPos = this.setParticuleDirection(p)
      let that = this
      p.draw = function () {
        that.ctx.beginPath()
        that.ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true)
        that.ctx.fillStyle = p.color
        that.ctx.fill()
      }
      return p
    },
    createCircle(x, y) {
      var p = {}
      p.x = x
      p.y = y
      p.color = "#FFF"
      p.radius = 0.1
      p.alpha = 0.5
      p.lineWidth = 6
      let that = this
      p.draw = function () {
        that.ctx.globalAlpha = p.alpha
        that.ctx.beginPath()
        that.ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true)
        that.ctx.lineWidth = p.lineWidth
        that.ctx.strokeStyle = p.color
        that.ctx.stroke()
        that.ctx.globalAlpha = 1
      }
      return p
    },
    renderParticule(anim) {
      for (var i = 0; i < anim.animatables.length; i++) {
        anim.animatables[i].target.draw()
      }
    },
    animateParticules(x, y) {
      var numberOfParticules = Number(location.href.split("?")[1]) || 40
      var circle = this.createCircle(x, y)
      var particules = []
      for (var i = 0; i < numberOfParticules; i++) {
        particules.push(this.createParticule(x, y))
      }
      anime
        .timeline()
        .add({
          targets: particules,
          x: function (p) {
            return p.endPos.x
          },
          y: function (p) {
            return p.endPos.y
          },
          radius: 0.1,
          duration: anime.random(1200, 1800),
          easing: "easeOutExpo",
          update: this.renderParticule,
        })
        .add({
          targets: circle,
          radius: anime.random(80, 160),
          lineWidth: 0,
          alpha: {
            value: 0,
            easing: "linear",
            duration: anime.random(600, 800),
          },
          duration: anime.random(1200, 1800),
          easing: "easeOutExpo",
          update: this.renderParticule,
          offset: 0,
        })
    },
  },
}
</script>

<style lang="scss" scoped>
.container {
  position: fixed;
  z-index: 2100000000;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none; // 点击事件穿透，使得鼠标点击可以穿透波纹，兼容ie11及以上
}
</style>
